package com.lakeworks.service.impl;

import com.lakeworks.common.core.domain.AjaxResult;
import com.lakeworks.common.core.text.Convert;
import com.lakeworks.common.domain.channel.ProductItem;
import com.lakeworks.common.domain.channel.ShipmentStatus;
import com.lakeworks.common.enums.PostRecordEnum;
import com.lakeworks.common.enums.ShipMentType;
import com.lakeworks.common.enums.StatusRecordEnum;
import com.lakeworks.common.utils.SecurityUtils;
import com.lakeworks.common.utils.ServletUtils;
import com.lakeworks.common.utils.uuid.IdUtils;
import com.lakeworks.domain.OprProduct;
import com.lakeworks.domain.OprShipment;
import com.lakeworks.domain.SysChannel;
import com.lakeworks.domain.SysProduct;
import com.lakeworks.domain.vo.PackageQueryPara;
import com.lakeworks.domain.vo.PickListVo;
import com.lakeworks.domain.vo.ShipmentItem;
import com.lakeworks.domain.vo.ShipmentVo;
import com.lakeworks.mapper.OprPickupMapper;
import com.lakeworks.mapper.OprProductMapper;
import com.lakeworks.mapper.OprShipmentMapper;
import com.lakeworks.mapper.SysChannelMapper;
import com.lakeworks.service.IOprShipmentService;
import com.lakeworks.service.ISysProductService;
import com.lakeworks.service.api.MerchantAsync;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * 出厂单Service业务层处理
 *
 * @author lake
 * @date 2023-02-08
 */
@Service
public class OprShipmentServiceImpl implements IOprShipmentService {


    @Autowired
    private OprShipmentMapper oprShipmentMapper;

    @Autowired
    private OprProductMapper oprProductMapper;

    @Autowired
    private ISysProductService sysProductService;

    @Autowired
    private SysChannelMapper sysChannelMapper;

    @Resource
    private OprPickupMapper oprPickupMapper;

    @Autowired
    private MerchantAsync merchantAsync;

    @Override
    public OprShipment selectByChannelIdAndChShipmentNo(Long channelId, String chShipmentNo) {
        return oprShipmentMapper.queryByChannelIdAndChShipmentNo(channelId, chShipmentNo);
    }

    @Override
    public int countByChShipmentNo(String chShipmentNo) {
        return oprShipmentMapper.countByChshipmentNo(chShipmentNo);
    }

    @Override
    public List<ProductItem> productItemById(Long id) {
        return oprShipmentMapper.productItemById(id);
    }

    /**
     * 查询出厂单
     *
     * @param id 出厂单主键
     * @return 出厂单
     */
    @Override
    public OprShipment selectOprShipmentById(Long id) {
        return oprShipmentMapper.selectOprShipmentById(id);
    }

    /**
     * 查询出厂单列表
     *
     * @param oprShipment 出厂单
     * @return 出厂单
     */
    @Override
    public List<OprShipment> selectOprShipmentList(OprShipment oprShipment) {
        return oprShipmentMapper.selectOprShipmentList(oprShipment);
    }

    @Override
    public List<OprShipment> selectShipmentList(OprShipment oprShipment) {
        return oprShipmentMapper.selectShipmentList(oprShipment);
    }

    /**
     * 新增出厂单
     *
     * @param oprShipment 出厂单
     * @return 结果
     */
    @Override
    public int insertOprShipment(OprShipment oprShipment) {
        int flag = oprShipmentMapper.insertOprShipment(oprShipment);
        if (flag == 0)
            throw new RuntimeException("出厂单保存失败！");
        return flag;
    }

    /**
     * 修改出厂单
     *
     * @param oprShipment 出厂单
     * @return 结果
     */
    @Override
    public int updateOprShipment(OprShipment oprShipment) {
        int flag = oprShipmentMapper.updateOprShipment(oprShipment);
        if (flag == 0)
            throw new RuntimeException("物流信息保存失败");
        return flag;
    }

    /**
     * 批量删除出厂单
     *
     * @param ids 需要删除的出厂单主键
     * @return 结果
     */
    @Override
    public int deleteOprShipmentByIds(String ids) {
        return oprShipmentMapper.deleteOprShipmentByIds(Convert.toStrArray(ids));
    }

    /**
     * 删除出厂单信息
     *
     * @param id 出厂单主键
     * @return 结果
     */
    @Override
    public int deleteOprShipmentById(Long id) {
        return oprShipmentMapper.deleteOprShipmentById(id);
    }

    @Override
    public OprShipment selectByExpressNo(String expressNo) {
        return oprShipmentMapper.queryByExpressNo(expressNo);
    }

    @Override
    public AjaxResult picking(List<Long> ShipmentIds) {
        //if (CollectionUtil.isEmpty(ShipmentIds)) {
        if (ShipmentIds == null || ShipmentIds.isEmpty()) {
            return AjaxResult.error("参数错误");
        }
        List<OprShipment> list = new ArrayList<>();
        AtomicInteger num = new AtomicInteger();
        ShipmentIds.forEach(id -> {
            OprShipment shipment = oprShipmentMapper.selectOprShipmentById(id);
            if (shipment.getStatus().equals(ShipMentType.TOPICK.getValue())) {
                shipment.setStatus(ShipMentType.PICKING.getValue());
                oprShipmentMapper.updateOprShipment(shipment);
                //保存出厂单拣货中状态改变记录
                OperateRecordUtil.commonImportRecord(StatusRecordEnum.SHIPMENT, shipment.getId(), shipment.getStatus());
                //给渠道回写出厂单拣货中状态
                merchantAsync.backShipState(ShipmentStatus.builder()
                        .shipmentNo(shipment.getChShipmentNo())
                        .status(ShipMentType.instance(shipment.getStatus()).toString())
                        .build(), shipment.getChannelId());
            }
            List<ShipmentVo> vos = new ArrayList<>();
            List<OprProduct> oprProducts = oprProductMapper.selectProductByShipmentId(id);
            num.addAndGet(oprProducts.size());
            //if (CollectionUtil.isNotEmpty(oprProducts)) {
            if (!oprProducts.isEmpty()) {
                oprProducts.forEach(oprProduct -> {
                    SysProduct product = sysProductService.selectSysProductById(oprProduct.getProductId());
                    ShipmentVo vo = ShipmentVo.builder().barcode(oprProduct.getBarcode()).name(product.getName()).category(product.getCategory()).build();
                    vos.add(vo);
//                    if (Objects.isNull(OperateRecordUtil.getPostRecord(PostRecordEnum.SORT, oprProduct.getId()))) {
//                        OperateRecordUtil.commonPostRecord(PostRecordEnum.SORT, oprProduct.getId());
//                    }
                });
                shipment.setOrderNo(oprPickupMapper.selectOprPickupById(oprProducts.get(0).getPickupId()).getOrderNo());
            }
            SysChannel channel = sysChannelMapper.selectSysChannelById(shipment.getChannelId());
            shipment.setClothesNum(vos.stream().map(ShipmentVo::getCategory).filter("CLOTHES"::equals).count());
            shipment.setShoesNum(vos.stream().map(ShipmentVo::getCategory).filter("SHOES"::equals).count());
            shipment.setLuxuryNum(vos.stream().map(ShipmentVo::getCategory).filter("LUXURY"::equals).count());
            shipment.setChannelName(channel.getName());
            shipment.setChannelCode(channel.getCode());
            shipment.setShipmentVoList(vos);
            list.add(shipment);
        });
        PickListVo pickNum = PickListVo.builder()
                .pickNum(IdUtils.SeqGenerator("1", 8))
                .shipmentNum(ShipmentIds.size())
                .totalNum(num.intValue()).list(list).build();
        return AjaxResult.success(pickNum);
    }

    @Override
    public int outFactory(Long id) {
        OprShipment shipment = new OprShipment();
        shipment.setId(id);
        shipment.setStatus(ShipMentType.SHIPPED.getValue());
        return oprShipmentMapper.updateOprShipment(shipment);
    }

    @Override
    public int shipmentsCountByNoAndHour(String status, PackageQueryPara para) {
        return oprShipmentMapper.shipmentsCountByNoAndHour(status, para);
    }

    @Override
    public List<ShipmentItem> shipmentsByNoAndHour(String status, PackageQueryPara para) {
        return oprShipmentMapper.shipmentsByNoAndHour(status, para);
    }

    @Override
    public List<OprShipment> queryShipmentsByDistribution(OprShipment oprShipment) {
        return oprShipmentMapper.queryShipmentsByDistribution(oprShipment);
    }
}
